home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / util / misc / adpcm_pa.lha / FP_ADPCM / DeliPlayers / Source / ADPCM-Player.c next >
C/C++ Source or Header  |  1995-10-05  |  21KB  |  932 lines

  1.  
  2. /*         DeliTracker-Player for ADPCM audio samples           */
  3. /* Written in 1995 by Christian Buchner. This is Public Domain. */
  4.  
  5. /* Note: TAB SIZE = 4 */
  6.  
  7. /* History:
  8.  
  9.    added version string (still V1.0)
  10.  
  11.    V1.1: reduced chip buffer size to 1K
  12.  
  13.    V1.2: rewritten for loading constantly while playing
  14.          added dummy NotePlayer interface, makes Stereoscope etc. work
  15.  
  16. */
  17.  
  18. /* Includes */
  19.  
  20. #include <proto/dos.h>
  21. #include <proto/exec.h>
  22. #include <proto/intuition.h>
  23. #include <libraries/dos.h>
  24. #include <dos/dostags.h>
  25. #include <utility/tagitem.h>
  26. #include <devices/audio.h>
  27. #include <exec/execbase.h>
  28. #include <exec/memory.h>
  29. #include <string.h>
  30. #include <stdarg.h>
  31. #include "DeliPlayer.h"
  32.  
  33.  
  34. /* Version String */
  35.  
  36. #define PLAYER_VERSION 1
  37. #define PLAYER_REVISION 2
  38.  
  39. UBYTE Version[]="$VER: ADPCM-Player 1.2 "__AMIGADATE__" by Christian Buchner";
  40.  
  41.  
  42. /* Externals */
  43.  
  44. extern struct DosLibrary *DOSBase;
  45. extern struct IntuitionBase *IntuitionBase;
  46.  
  47. /* DeliTracker's stuff */
  48.  
  49. struct DeliTrackerGlobals *DeliBase;
  50. struct MsgPort *DeliPort;
  51.  
  52. /* Copyright and info */
  53.  
  54. UBYTE AboutString[]="a player for ADPCM audio samples\n"
  55.                     "in MONO ADPCM2 or ADPCM3 format.\n"
  56.                     "(c) 1995 by Christian Buchner";
  57.  
  58.  
  59. void __asm __saveds DeliProcess(void);
  60. ULONG __asm __saveds Check(void);
  61. ULONG __asm __saveds InitPlayer(void);
  62. ULONG __asm __saveds EndPlayer(void);
  63. ULONG __asm __saveds InitSound(void);
  64. ULONG __asm __saveds EndSound(void);
  65. ULONG __asm __saveds StartInt(void);
  66. ULONG __asm __saveds StopInt(void);
  67. ULONG __asm __saveds Faster(void);
  68. ULONG __asm __saveds Slower(void);
  69. ULONG __asm __saveds VolBalance(void);
  70. void SetPerVol(void);
  71. void __stdargs Message(UBYTE *Msg,...);
  72.  
  73. struct NoteStruct *NotePlay;
  74.  
  75. extern __asm ULONG DecompressADPCM2(    register __a0 UBYTE *Source,
  76.                                         register __d0 ULONG Length,
  77.                                         register __a1 UBYTE *Destination,
  78.                                         register __d1 ULONG JoinCode    );
  79.  
  80. extern __asm ULONG DecompressADPCM3(    register __a0 UBYTE *Source,
  81.                                         register __d0 ULONG Length,
  82.                                         register __a1 UBYTE *Destination,
  83.                                         register __d1 ULONG JoinCode    );
  84.  
  85.  
  86. /* Tag list for DeliTracker */
  87.  
  88. struct TagItem PlayerTagArray[]=
  89. {
  90.     DTP_RequestDTVersion,    17,
  91.     DTP_PlayerVersion,        (PLAYER_VERSION<<16)+10*PLAYER_REVISION,
  92.     DTP_PlayerName,            (ULONG)"ADPCM-Player",
  93.     DTP_Creator,            (ULONG)AboutString,
  94.     DTP_Description,        (ULONG)"a player for ADPCM samples",
  95.     DTP_Flags,                PLYF_SONGEND,
  96.     DTP_DeliBase,            (ULONG)&DeliBase,
  97.     DTP_Check1,                (ULONG)&Check,
  98.     DTP_Process,            (ULONG)&DeliProcess,
  99.     DTP_Priority,            0,
  100.     DTP_StackSize,            4096,
  101.     DTP_MsgPort,            (ULONG)&DeliPort,
  102.     DTP_NoteStruct,            (ULONG)&NotePlay,
  103.     DTP_InitPlayer,            (ULONG)&InitPlayer,
  104.     DTP_EndPlayer,            (ULONG)&EndPlayer,
  105.     DTP_InitSound,            (ULONG)&InitSound,
  106.     DTP_EndSound,            (ULONG)&EndSound,
  107.     DTP_StartInt,            (ULONG)&StartInt,
  108.     DTP_StopInt,            (ULONG)&StopInt,
  109.     DTP_Volume,                (ULONG)&VolBalance,
  110.     DTP_Balance,            (ULONG)&VolBalance,
  111.     DTP_Faster,                (ULONG)&Faster,
  112.     DTP_Slower,                (ULONG)&Slower,
  113.     TAG_DONE
  114. };
  115.  
  116.  
  117. /* The primitive sample header */
  118.  
  119. struct ADPCMHeader
  120. {
  121.     UBYTE Identifier[6];
  122.     ULONG Frequency;
  123. };
  124.  
  125. UBYTE IDString[]="ADPCM";
  126.  
  127. struct Process *PlayerTask;
  128.  
  129. BOOL ChanInit;
  130. struct MsgPort *LeftReply[3];        /* 2 for buffers, 1 for period/volume */
  131. struct MsgPort *RightReply[3];
  132. struct IOAudio *LeftAudio[3];
  133. struct IOAudio *RightAudio[3];
  134.  
  135. #define CHIP_SIZE 1024
  136. UBYTE *ChipBuffer[2];
  137.  
  138. /* specifies the buffer size in _decrunched_ bytes */
  139. #define LOAD_SIZE (128*CHIP_SIZE)
  140.  
  141. /* specifies the length of the load queue */
  142. #define QUEUE_LEN 2
  143.  
  144. BPTR LoadHandle;
  145. ULONG FileSize;
  146.  
  147. struct LoadBuffer
  148. {
  149.     struct MinNode lb_Node;
  150.     ULONG lb_ADPCMPosition;
  151.     UBYTE *lb_ADPCMData;
  152.     ULONG lb_ADPCMLen;
  153.     ULONG lb_PlayOffset;
  154. };
  155.  
  156. struct List BufferList;
  157. UWORD NumBuffers;
  158. struct SignalSemaphore BufferSemaphore;
  159. struct SignalSemaphore LoadQuitSemaphore;
  160.  
  161. struct Process *LoadProc;
  162. void __saveds LoadBuffers(void);
  163.  
  164. ULONG Bits;
  165. ULONG Frequency;
  166. ULONG LeftVolume=64;
  167. ULONG RightVolume=64;
  168.  
  169. ULONG ADPCMLen;
  170. ULONG ADPCMPosition;
  171. BOOL Loading=FALSE;
  172. BOOL LoadingStopped=TRUE;
  173.  
  174. BOOL Playing;
  175. BOOL BufPlaying[2];
  176. ULONG PlayPosition;
  177. ULONG JoinCode;
  178.  
  179.  
  180. /*** NotePlayer interface ***/
  181.  
  182. struct NoteChannel NoteChannels[2]=
  183. {
  184.     &NoteChannels[1],        /* NextChannel */
  185.     0,                        /* for use by NotePlayer */
  186.     0,                        /* Reserved0 */
  187.     0,                        /* Private */
  188.     0,                        /* Changed */
  189.     NCHD_FarLeft,0,            /* StereoPos, Stereo */
  190.     0,0,                    /* SampleStart, SampleLength */
  191.     0,0,                    /* RepeatStart, RepeatLength */
  192.     0,                        /* Frequency */
  193.     0,                        /* Volume */
  194.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* Reserved1 */
  195.     
  196.     NULL,                    /* NextChannel */
  197.     0,                        /* for use by NotePlayer */
  198.     0,                        /* Reserved0 */
  199.     0,                        /* Private */
  200.     0,                        /* Changed */
  201.     NCHD_FarRight,0,        /* StereoPos, Stereo */
  202.     0,0,                    /* SampleStart, SampleLength */
  203.     0,0,                    /* RepeatStart, RepeatLength */
  204.     0,                        /* Frequency */
  205.     0,                        /* Volume */                      
  206.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0            /* Reserved1 */
  207. };
  208.  
  209. struct NoteStruct NoteStruct=
  210. {
  211.     &NoteChannels[0],                                /* Channels */
  212.     NSTF_Dummy|NSTF_Period|NSTF_Signed|NSTF_8Bit,    /* Flags */
  213.     28867,                                            /* Max Frequency */
  214.     64,                                                /* Max Volume */
  215.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0                /* reserved */
  216. };
  217.  
  218. struct NoteStruct *NotePlay = &NoteStruct;
  219.  
  220.  
  221. /****************************************************************************/
  222.  
  223. /* Our player's Process */
  224.  
  225. void __asm __saveds DeliProcess(void)
  226. {
  227.     BOOL ProcActive=TRUE;
  228.     ULONG Signals;
  229.     struct DeliMessage *DeliMessage;
  230.     
  231.     DOSBase=(struct DosLibrary*)DeliBase->DOSBase;
  232.     IntuitionBase=(struct IntuitionBase*)DeliBase->IntuitionBase;
  233.     
  234.     PlayerTask=(struct Process*)FindTask(NULL);
  235.     PlayerTask->pr_Task.tc_Node.ln_Pri=22;
  236.     
  237.     NewList(&BufferList);
  238.     InitSemaphore(&BufferSemaphore);
  239.     InitSemaphore(&LoadQuitSemaphore);
  240.     
  241.     if (LoadProc=CreateNewProcTags(    NP_Entry, &LoadBuffers,
  242.                                     NP_Name, "ADPCM Loader",
  243.                                     NP_Priority, 21,
  244.                                     TAG_DONE ))
  245.     {
  246.         BOOL NoteInit=FALSE;
  247.         UBYTE *NotePosition=NULL;
  248.         ULONG NoteLength=0;
  249.         UWORD NotePeriod=0;
  250.         
  251.         while(ProcActive)
  252.         {
  253.             ULONG SigMask = SIGBREAKF_CTRL_C | (1L<<DeliPort->mp_SigBit);
  254.             
  255.             if (ChanInit) SigMask |=    (1L<<LeftReply[0]->mp_SigBit) | 
  256.                                         (1L<<LeftReply[1]->mp_SigBit) ;
  257.             
  258.             Signals=Wait(SigMask);
  259.             
  260.             if (Signals & SIGBREAKF_CTRL_C)
  261.             {
  262.                 ProcActive=FALSE;
  263.             }
  264.             
  265.             if (Signals & (1L<<DeliPort->mp_SigBit))
  266.             {
  267.                 if (DeliMessage=(struct DeliMessage*)GetMsg(DeliPort))
  268.                 {
  269.                     DeliMessage->Result=(DeliMessage->Function)();
  270.                     ReplyMsg((struct Message*)DeliMessage);
  271.                 }
  272.             }
  273.             
  274.             if (ChanInit)
  275.             {
  276.                 UWORD i;
  277.                 
  278.                 for (i=0;i<2;i++)
  279.                 {
  280.                     if (Signals & (1L<<LeftReply[i]->mp_SigBit))
  281.                     {
  282.                         if (BufPlaying[i])
  283.                         {
  284.                             WaitPort(LeftReply[i]);        GetMsg(LeftReply[i]);
  285.                             WaitPort(RightReply[i]);    GetMsg(RightReply[i]);
  286.                             BufPlaying[i]=FALSE;
  287.                         }
  288.                         
  289.                         if (Playing)
  290.                         {
  291.                             if (NoteInit)
  292.                             {
  293.                                 NoteChannels[0].nch_SampleStart=
  294.                                 NoteChannels[0].nch_RepeatStart=
  295.                                 NoteChannels[1].nch_SampleStart=
  296.                                 NoteChannels[1].nch_RepeatStart=NotePosition;
  297.                                 
  298.                                 NoteChannels[0].nch_SampleLength=
  299.                                 NoteChannels[0].nch_RepeatLength=
  300.                                 NoteChannels[1].nch_SampleLength=
  301.                                 NoteChannels[0].nch_RepeatLength=NoteLength;
  302.                                 
  303.                                 NoteChannels[0].nch_Frequency=
  304.                                 NoteChannels[1].nch_Frequency=NotePeriod;
  305.                                 
  306.                                 NoteChannels[0].nch_Volume=64;
  307.                                 NoteChannels[1].nch_Volume=64;
  308.                                 
  309.                                 NoteChannels[0].nch_Changed=
  310.                                 NoteChannels[1].nch_Changed=NCHF_Sample|NCHF_Repeat|NCHF_Frequency|NCHF_Volume;
  311.                                 
  312.                                 dt_NotePlayer();
  313.                             }
  314.                             
  315.                             if (PlayPosition > ADPCMLen)
  316.                             {
  317.                                 Message("WARNING! PlayPosition > ADPCMLen!?!");
  318.                             }
  319.                             
  320.                             if (PlayPosition>=ADPCMLen)
  321.                             {
  322.                                 /* Signal Songend */
  323.                                 dt_SongEnd();
  324.                             }
  325.                             
  326.                             ObtainSemaphore(&BufferSemaphore);
  327.                             
  328.                             if (NumBuffers > 0)
  329.                             {
  330.                                 struct LoadBuffer *lb;
  331.                                 
  332.                                 ULONG Do;
  333.                                 ULONG ChipMax;
  334.                                 ULONG DMALen;
  335.                                 
  336.                                 lb=(struct LoadBuffer*)BufferList.lh_Head;
  337.                                 
  338.                                 if (    lb->lb_ADPCMPosition==0 &&
  339.                                         lb->lb_PlayOffset==0        )
  340.                                 {
  341.                                     JoinCode=0;
  342.                                 }
  343.                                 
  344.                                 if (Bits==2) ChipMax = (CHIP_SIZE+3)/4;
  345.                                 if (Bits==3) ChipMax = (CHIP_SIZE+7)/8*3;
  346.                                 
  347.                                 Do=lb->lb_ADPCMLen-lb->lb_PlayOffset;
  348.                                 if (Do>ChipMax) Do=ChipMax;
  349.                                 
  350.                                 if (Do>0)
  351.                                 {
  352.                                     UWORD Period=(*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
  353.                                     
  354.                                     if (Bits==2) JoinCode=DecompressADPCM2(lb->lb_ADPCMData+lb->lb_PlayOffset, Do, ChipBuffer[i], JoinCode);
  355.                                     if (Bits==3) JoinCode=DecompressADPCM3(lb->lb_ADPCMData+lb->lb_PlayOffset, Do, ChipBuffer[i], JoinCode);
  356.                                     
  357.                                     lb->lb_PlayOffset += Do;
  358.                                     PlayPosition=lb->lb_ADPCMPosition+lb->lb_PlayOffset;
  359.                                     
  360.                                     if (Bits==2) DMALen = Do*4;
  361.                                     if (Bits==3) DMALen = Do*8/3;
  362.                                     
  363.                                     LeftAudio[i]->ioa_Data =
  364.                                     RightAudio[i]->ioa_Data = ChipBuffer[i];
  365.                                     
  366.                                     LeftAudio[i]->ioa_Length =
  367.                                     RightAudio[i]->ioa_Length = DMALen;
  368.                                     
  369.                                     LeftAudio[i]->ioa_Period = 
  370.                                     RightAudio[i]->ioa_Period= Period;
  371.                                     
  372.                                     LeftAudio[i]->ioa_Volume=LeftVolume;
  373.                                     RightAudio[i]->ioa_Volume=RightVolume;
  374.                                     
  375.                                     LeftAudio[i]->ioa_Cycles=
  376.                                     RightAudio[i]->ioa_Cycles=1;
  377.                                     
  378.                                     LeftAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  379.                                     RightAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  380.                                     
  381.                                     LeftAudio[i]->ioa_Request.io_Command=
  382.                                     RightAudio[i]->ioa_Request.io_Command=CMD_WRITE;
  383.                                     
  384.                                     Forbid();
  385.                                     BeginIO(LeftAudio[i]);
  386.                                     BeginIO(RightAudio[i]);
  387.                                     BufPlaying[i]=TRUE;
  388.                                     Permit();
  389.                                     
  390.                                     NotePosition=ChipBuffer[i];
  391.                                     NoteLength=DMALen;
  392.                                     NotePeriod=Period;
  393.                                     NoteInit=TRUE;
  394.                                 }
  395.                                 
  396.                                 if (ADPCMPosition > ADPCMLen)
  397.                                 {
  398.                                     Message("WARNING! lb_PlayOffset > lb_ADPCMLen!?!");
  399.                                 }
  400.                                 
  401.                                 if (lb->lb_PlayOffset >= lb->lb_ADPCMLen)
  402.                                 {
  403.                                     Remove((struct Node*)lb);
  404.                                     NumBuffers--;
  405.                                     
  406.                                     Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
  407.                                     
  408.                                     if (lb->lb_ADPCMData)
  409.                                     {
  410.                                         FreeVec(lb->lb_ADPCMData);
  411.                                         lb->lb_ADPCMData=NULL;
  412.                                     }
  413.                                     
  414.                                     FreeVec(lb);
  415.                                     lb=NULL;
  416.                                 }
  417.                             }
  418.                             
  419.                             ReleaseSemaphore(&BufferSemaphore);
  420.                         }
  421.                     }
  422.                 }
  423.             }
  424.         }
  425.         Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_C);
  426.         ObtainSemaphore(&LoadQuitSemaphore);
  427.     }
  428. }
  429.  
  430.  
  431. /****************************************************************************/
  432.  
  433. void __saveds LoadBuffers(void)
  434. {
  435.     ULONG Signals;
  436.     BOOL LoadActive=TRUE;
  437.     
  438.     ObtainSemaphore(&LoadQuitSemaphore);
  439.     
  440.     while (LoadActive)
  441.     {
  442.         Signals=Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
  443.         
  444.         if (Signals & SIGBREAKF_CTRL_C)
  445.         {
  446.             LoadActive=FALSE;
  447.         }
  448.         
  449.         if (Signals & SIGBREAKF_CTRL_D)
  450.         {
  451.             if (Loading==FALSE)
  452.             {
  453.                 LoadingStopped=TRUE;
  454.                 
  455.                 Signal(PlayerTask, SIGBREAKF_CTRL_D);
  456.             }
  457.             else
  458.             {
  459.                 LoadingStopped=FALSE;
  460.                 
  461.                 if (LoadHandle && ADPCMLen>sizeof(struct ADPCMHeader))
  462.                 {
  463.                     while (NumBuffers < QUEUE_LEN)
  464.                     {
  465.                         struct LoadBuffer *lb;
  466.                         if (lb=AllocVec(sizeof(struct LoadBuffer),MEMF_ANY|MEMF_CLEAR))
  467.                         {
  468.                             BOOL Success=FALSE;
  469.                             
  470.                             ULONG Do = ADPCMLen - ADPCMPosition;
  471.                             ULONG Max;
  472.                             if (Bits==2) Max=(LOAD_SIZE+3)/4;
  473.                             if (Bits==3) Max=(LOAD_SIZE+7)/8*3;
  474.                             if (Do > Max) Do=Max;
  475.                             
  476.                             if (Do)
  477.                             {
  478.                                 if (lb->lb_ADPCMData=AllocVec(Do, MEMF_ANY))
  479.                                 {
  480.                                     LONG Got;
  481.                                     Seek(    LoadHandle,
  482.                                             ADPCMPosition+sizeof(struct ADPCMHeader),
  483.                                             OFFSET_BEGINNING );
  484.                                     
  485.                                     Got=Read(LoadHandle, lb->lb_ADPCMData, Do);
  486.                                     
  487.                                     if (Got < 0)
  488.                                     {
  489.                                         Message("Read error!");
  490.                                     }
  491.                                     else
  492.                                     {
  493.                                         if (Got != Do)
  494.                                         {
  495.                                             Message("Warning, short read! Wanted %ld, got %ld",Do,Got);
  496.                                         }
  497.                                         
  498.                                         if (Got != 0) Success=TRUE;
  499.                                         
  500.                                         lb->lb_ADPCMPosition=ADPCMPosition;
  501.                                         lb->lb_ADPCMLen=Got;
  502.                                         ADPCMPosition+=Got;
  503.                                         
  504.                                         if (ADPCMPosition > ADPCMLen)
  505.                                         {
  506.                                             Message("WARNING! Position > Filesize!?!");
  507.                                         }
  508.                                         
  509.                                         /* Restart loading */
  510.                                         if (ADPCMPosition >= ADPCMLen)
  511.                                         {
  512.                                             ADPCMPosition = 0;
  513.                                         }
  514.                                     }
  515.                                 }
  516.                             }
  517.                             
  518.                             if (Success)
  519.                             {
  520.                                 ObtainSemaphore(&BufferSemaphore);
  521.                                 AddTail(&BufferList,(struct Node*)lb);
  522.                                 NumBuffers++;
  523.                                 
  524.                                 if (    NumBuffers    == QUEUE_LEN &&
  525.                                         BufPlaying[0] == FALSE     &&
  526.                                         BufPlaying[1] == FALSE          )
  527.                                 {
  528.                                     Signal(PlayerTask,(1L<<LeftReply[0]->mp_SigBit));
  529.                                     Signal(PlayerTask,(1L<<LeftReply[1]->mp_SigBit));
  530.                                 }
  531.                                 
  532.                                 ReleaseSemaphore(&BufferSemaphore);
  533.                             }
  534.                             else
  535.                             {
  536.                                 if (lb->lb_ADPCMData)
  537.                                 {
  538.                                     FreeVec(lb->lb_ADPCMData);
  539.                                     lb->lb_ADPCMData=NULL;
  540.                                 }
  541.                                 FreeVec(lb);
  542.                                 lb=NULL;
  543.                             }
  544.                         }
  545.                     }
  546.                 }
  547.             }
  548.         }
  549.     }
  550.     
  551.     Forbid();
  552.     ReleaseSemaphore(&LoadQuitSemaphore);
  553. }
  554.  
  555.  
  556. /****************************************************************************/
  557.  
  558. /* Module check routine */
  559.  
  560. ULONG __asm __saveds Check(void)
  561. {
  562.     BOOL Result=TRUE;
  563.     
  564.     struct ADPCMHeader *Header=(struct ADPCMHeader*)(DeliBase->ChkData);
  565.     
  566.     if (!strncmp(IDString,Header->Identifier,strlen(IDString)))
  567.     {
  568.         if ( Header->Identifier[5]=='2' ||
  569.              Header->Identifier[5]=='3' )
  570.         {
  571.             if (Header->Identifier[5]=='2') Bits=2;
  572.             if (Header->Identifier[5]=='3') Bits=3;
  573.             Frequency=Header->Frequency;
  574.             
  575.             Result=FALSE;
  576.         }
  577.     }
  578.     return(Result);
  579. }
  580.  
  581.  
  582. /****************************************************************************/
  583.  
  584. /* Init player (alloc channels, etc...) */
  585.  
  586. ULONG __asm __saveds InitPlayer(void)
  587. {
  588.     BOOL Error=TRUE;
  589.     
  590.     if (LoadHandle=Open(DeliBase->PathArrayPtr,MODE_OLDFILE))
  591.     {
  592.         struct FileInfoBlock *fib;
  593.         if (fib=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_ANY))
  594.         {
  595.             UBYTE LeftArray[2]={1,8};
  596.             UBYTE RightArray[2]={2,4};
  597.             UWORD i;
  598.             
  599.             if (ExamineFH(LoadHandle, fib))
  600.             {
  601.                 FileSize = fib->fib_Size;
  602.             }
  603.             else
  604.             {
  605.                 Seek(LoadHandle, 0, OFFSET_END);
  606.                 FileSize = Seek(LoadHandle, 0, OFFSET_BEGINNING);
  607.             }
  608.             
  609.             FreeMem(fib, sizeof(struct FileInfoBlock));
  610.             
  611.             ADPCMLen = FileSize-sizeof(struct ADPCMHeader);
  612.             
  613.             for (i=0;i<3;i++)
  614.             {
  615.                 if (!(LeftReply[i]=CreateMsgPort())) break;
  616.                 if (!(RightReply[i]=CreateMsgPort())) break;
  617.                 
  618.                 if (!(LeftAudio[i]=CreateIORequest(LeftReply[i],sizeof(struct IOAudio)))) break;
  619.                 if (!(RightAudio[i]=CreateIORequest(RightReply[i],sizeof(struct IOAudio)))) break;
  620.                 
  621.                 if (i<2) if (!(ChipBuffer[i]=AllocVec(CHIP_SIZE,MEMF_CHIP))) break;
  622.             }
  623.             if (i==3)
  624.             {
  625.                 LeftAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
  626.                 LeftAudio[0]->ioa_Length=sizeof(LeftArray);
  627.                 LeftAudio[0]->ioa_Data=LeftArray;
  628.                 LeftAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  629.                 if (!OpenDevice("audio.device",0L,(struct IORequest *)LeftAudio[0],0))
  630.                 {
  631.                     for (i=1;i<3;i++)
  632.                     {
  633.                         LeftAudio[i]->ioa_Request.io_Device=LeftAudio[0]->ioa_Request.io_Device;
  634.                         LeftAudio[i]->ioa_Request.io_Unit=LeftAudio[0]->ioa_Request.io_Unit;
  635.                         LeftAudio[i]->ioa_AllocKey=LeftAudio[0]->ioa_AllocKey;
  636.                     }
  637.                     RightAudio[0]->ioa_Length=sizeof(RightArray);
  638.                     RightAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
  639.                     RightAudio[0]->ioa_Data=RightArray;
  640.                     RightAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  641.                     if (!OpenDevice("audio.device",0L,(struct IORequest *)RightAudio[0],0))
  642.                     {
  643.                         for (i=1;i<3;i++)
  644.                         {
  645.                             RightAudio[i]->ioa_Request.io_Device=RightAudio[0]->ioa_Request.io_Device;
  646.                             RightAudio[i]->ioa_Request.io_Unit=RightAudio[0]->ioa_Request.io_Unit;
  647.                             RightAudio[i]->ioa_AllocKey=RightAudio[0]->ioa_AllocKey;
  648.                         }
  649.                         
  650.                         ChanInit=TRUE;
  651.                         
  652.                         Error=FALSE;
  653.                     }
  654.                 }
  655.             }
  656.         }
  657.     }
  658.     
  659.     if (Error)
  660.     {
  661.         EndPlayer();
  662.     }
  663.     
  664.     DeliBase->SndNum=1;
  665.     
  666.     return(Error);
  667. }
  668.  
  669.  
  670. /****************************************************************************/
  671.  
  672. /* Clean up the Player (deallocate, etc..) */
  673.  
  674. ULONG __asm __saveds EndPlayer(void)
  675. {
  676.     WORD i;
  677.     
  678.     for (i=2;i>=0;i--)
  679.     {
  680.         if (i<2)
  681.         {
  682.             if (ChipBuffer[i])
  683.             {
  684.                 FreeVec(ChipBuffer[i]);
  685.                 ChipBuffer[i]=NULL;
  686.             }
  687.         }
  688.         
  689.         if (RightAudio[i])
  690.         {
  691.             if (i==0 && RightAudio[i]->ioa_Request.io_Device)
  692.             {
  693.                 CloseDevice(RightAudio[i]);
  694.                 RightAudio[i]->ioa_Request.io_Device=NULL;
  695.             }
  696.             DeleteIORequest(RightAudio[i]);
  697.             RightAudio[i]=NULL;
  698.         }
  699.         
  700.         if (RightReply[i])
  701.         {
  702.             DeleteMsgPort(RightReply[i]);
  703.             RightReply[i]=NULL;
  704.         }
  705.         
  706.         if (LeftAudio[i])
  707.         {
  708.             if (i==0 && LeftAudio[i]->ioa_Request.io_Device)
  709.             {
  710.                 CloseDevice(LeftAudio[i]);
  711.                 LeftAudio[i]->ioa_Request.io_Device=NULL;
  712.             }
  713.             DeleteIORequest(LeftAudio[i]);
  714.             LeftAudio[i]=NULL;
  715.         }
  716.         
  717.         if (LeftReply[i])
  718.         {
  719.             DeleteMsgPort(LeftReply[i]);
  720.             LeftReply[i]=NULL;
  721.         }
  722.     }
  723.     
  724.     if (LoadHandle)
  725.     {
  726.         Close(LoadHandle);
  727.         LoadHandle=NULL;
  728.     }
  729.     
  730.     ChanInit=FALSE;
  731.     
  732.     return(0);
  733. }
  734.  
  735.  
  736. /****************************************************************************/
  737.  
  738. /* Initialize the "Module" */
  739.  
  740. ULONG __asm __saveds InitSound(void)
  741. {
  742.     ADPCMPosition = 0;
  743.     Loading = TRUE;
  744.     Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
  745.     
  746.     return(0);
  747. }
  748.  
  749.  
  750. /****************************************************************************/
  751.  
  752. /* End sound */
  753.  
  754. ULONG __asm __saveds EndSound(void)
  755. {
  756.     struct LoadBuffer *lb,*nextlb;
  757.     
  758.     LoadingStopped=FALSE;
  759.     
  760.     Loading=FALSE;
  761.     
  762.     Forbid();
  763.     
  764.     while (!LoadingStopped)
  765.     {
  766.         Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
  767.         Wait(SIGBREAKF_CTRL_D);
  768.     }
  769.     
  770.     Permit();
  771.     
  772.     ObtainSemaphore(&BufferSemaphore);
  773.     
  774.     for(    lb=(struct LoadBuffer*)BufferList.lh_Head ;
  775.             nextlb = (struct LoadBuffer*)lb->lb_Node.mln_Succ ;
  776.             lb = nextlb    )
  777.     {
  778.         Remove((struct Node*)lb);
  779.         NumBuffers--;
  780.         
  781.         if (lb->lb_ADPCMData)
  782.         {
  783.             FreeVec(lb->lb_ADPCMData);
  784.             lb->lb_ADPCMData=NULL;
  785.         }
  786.         
  787.         FreeVec(lb);
  788.         lb=NULL;
  789.     }
  790.     
  791.     ReleaseSemaphore(&BufferSemaphore);
  792.     
  793.     return(0);
  794. }
  795.  
  796.  
  797. /****************************************************************************/
  798.  
  799. /* Start sound */
  800.  
  801. ULONG __asm __saveds StartInt(void)
  802. {
  803.     PlayPosition=0;
  804.     Playing=TRUE;
  805.     
  806.     if (NumBuffers == QUEUE_LEN)
  807.     {
  808.         Signal(PlayerTask,(1L<<LeftReply[0]->mp_SigBit));
  809.         Signal(PlayerTask,(1L<<LeftReply[1]->mp_SigBit));
  810.     }
  811.     
  812.     return(0);
  813. }
  814.  
  815.  
  816. /****************************************************************************/
  817.  
  818. /* Stop sound */
  819.  
  820. ULONG __asm __saveds StopInt(void)
  821. {
  822.     UWORD i;
  823.     
  824.     Playing=FALSE;
  825.     
  826.     for (i=0;i<2;i++)
  827.     {
  828.         if (BufPlaying[i])
  829.         {
  830.             AbortIO(LeftAudio[i]);
  831.             AbortIO(RightAudio[i]);
  832.             WaitPort(LeftReply[i]);        GetMsg(LeftReply[i]);
  833.             WaitPort(RightReply[i]);    GetMsg(RightReply[i]);
  834.             BufPlaying[i]=FALSE;
  835.         }
  836.     }
  837.     
  838.     return(0);
  839. }
  840.  
  841.  
  842. /****************************************************************************/
  843.  
  844. /* Play Faster */
  845.  
  846. ULONG __asm __saveds Faster(void)
  847. {
  848.     Frequency+=100;
  849.     
  850.     SetPerVol();
  851.     return(0);
  852. }
  853.  
  854.  
  855. /****************************************************************************/
  856.  
  857. /* Slower */
  858.  
  859. ULONG __asm __saveds Slower(void)
  860. {
  861.     Frequency-=100;
  862.     
  863.     SetPerVol();
  864.     return(0);
  865. }
  866.  
  867.  
  868. /****************************************************************************/
  869.  
  870. /* Volume and Balance */
  871.  
  872. ULONG __asm __saveds VolBalance(void)
  873. {
  874.     LeftVolume= DeliBase->SndVol*DeliBase->SndLBal/64;
  875.     RightVolume=DeliBase->SndVol*DeliBase->SndRBal/64;
  876.     
  877.     SetPerVol();
  878.     return(0);
  879. }
  880.  
  881.  
  882. /****************************************************************************/
  883.  
  884. /* Set Period and Volume */
  885.  
  886. void SetPerVol(void)
  887. {
  888.     UWORD i;
  889.     
  890.     UWORD Period= (*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
  891.     
  892.     for (i=0;i<3;i++)
  893.     {
  894.         LeftAudio[i]->ioa_Period = 
  895.         RightAudio[i]->ioa_Period=Period;
  896.         
  897.         LeftAudio[i]->ioa_Volume=LeftVolume;
  898.         RightAudio[i]->ioa_Volume=RightVolume;
  899.     }
  900.     
  901.     LeftAudio[2]->ioa_Request.io_Command=
  902.     RightAudio[2]->ioa_Request.io_Command=ADCMD_PERVOL;
  903.     
  904.     DoIO((struct IORequest*)LeftAudio[2]);
  905.     DoIO((struct IORequest*)RightAudio[2]);
  906. }
  907.  
  908.  
  909. /*******************************************************************************/
  910.  
  911. /* Show a message to the user */
  912.  
  913. void __stdargs Message(UBYTE *Msg,...)
  914. {
  915.     va_list Arg;
  916.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM-Player message",0,"Okay"};
  917.     Req.es_TextFormat=Msg;
  918.     va_start(Arg,Msg);
  919.     
  920.     if (IntuitionBase)
  921.     {
  922.         EasyRequestArgs(NULL,&Req,0,Arg);
  923.     }
  924.     else
  925.     {
  926.         VPrintf(Msg,Arg);
  927.         Printf("\n");
  928.     }
  929.     
  930.     va_end(Arg);
  931. }
  932.